<script lang="ts" setup>
import { NButton, NPopover, NScrollbar, NSpace, NSpin, NTag } from 'naive-ui';
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { $t } from '@/locales';
import { fetchImageData } from '@/service/api/media';

interface Props {
  seasons: Api.Media.MediaCollectionItemList[] | null;
  loading: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  seasons: null
});

const activeSeasonId = ref<number | null>(null);

function getRatingType(rating?: number): 'success' | 'warning' | 'error' {
  if (rating === undefined || rating === null) return 'warning';
  if (rating >= 8) return 'success';
  if (rating >= 6) return 'warning';
  return 'error';
}

function formatRating(rating?: number): string {
  if (rating === undefined || rating === null) return '-';
  return rating.toFixed(1);
}

function formatDate(date: string): string {
  return new Date(date).toLocaleString();
}

const EPISODE_NUMBER_REGEX = /[Ee](\d+)/;
const SEVEN_DAYS = 7 * 24 * 60 * 60 * 1000;

function formatEpisodeNumber(episode: Api.Media.MediaItem): string {
  const match = episode.name.match(EPISODE_NUMBER_REGEX);
  if (match) {
    return `E${match[1].padStart(2, '0')}`;
  }
  const pathMatch = episode.path.match(/[Ee](\d+)/i);
  if (pathMatch) {
    return `E${pathMatch[1].padStart(2, '0')}`;
  }
  return 'E??';
}

function isNewEpisode(lastWriteTime: string): boolean {
  const now = Date.now();
  const episodeDate = new Date(lastWriteTime).getTime();
  return now - episodeDate < SEVEN_DAYS;
}

interface EnhancedMediaItem extends Api.Media.MediaItem {
  isNew?: boolean;
  episodeNumber: string;
  formattedSize: string;
  formattedDate: string;
  bitrate?: number;
  duration?: number;
  subtitle?: string[];
}

interface EnhancedMediaCollectionItemList extends Omit<Api.Media.MediaCollectionItemList, 'data'> {
  data?: EnhancedMediaItem[];
}

const processedSeasons = computed<EnhancedMediaCollectionItemList[] | null>(() => {
  if (!props.seasons) return null;
  return props.seasons
    .filter(season => season && season.data !== undefined && season.data?.length > 0)
    .map(season => ({
      ...season,
      data: season.data
        ?.filter(episode => episode && episode.name)
        ?.map(episode => ({
          ...episode,
          isNew: isNewEpisode(episode.lastWriteTime),
          episodeNumber: formatEpisodeNumber(episode),
          formattedSize: episode.size.toString(),
          formattedDate: formatDate(episode.lastWriteTime)
        }))
        ?.sort((a, b) => {
          const getEpisodeNum = (ep: EnhancedMediaItem) => {
            const match = ep.episodeNumber.match(/\d+/);
            return match ? Number.parseInt(match[0], 10) : 0;
          };
          return getEpisodeNum(a) - getEpisodeNum(b);
        })
    }));
});


onMounted(() => {
  const contentElements = document.querySelectorAll('.section-content');
  contentElements.forEach(el => {
    if (checkContentOverflow(el as HTMLElement)) {
      el.classList.add('overflow');
    }
  });
});
// 创 Intersection Observer
const observer = ref<IntersectionObserver | null>(null);
// 添加图片相关状态
const episodeImages = ref<Record<string, string>>({});
const imageLoadErrors = ref<Set<string>>(new Set());
const imageLoading = ref<Set<string>>(new Set());
onBeforeUnmount(() => {
  // 断开 observer 连接
  if (observer.value) {
    observer.value.disconnect();
    observer.value = null;
  }
  // 清理图片资源
  Object.values(episodeImages.value).forEach(url => {
    URL.revokeObjectURL(url);
  });
  episodeImages.value = {};
  imageLoadErrors.value.clear();
  imageLoading.value.clear();
});

const listMode = ref(true);

function toggleListMode() {
  listMode.value = !listMode.value;
}

// 计算当前选中的季度
const seasonMap = computed(() => {
  if (!processedSeasons.value) return new Map();
  return new Map(processedSeasons.value.map(season => [season.season, season]));
});

const activeSeason = computed(() => {
  if (!seasonMap.value || activeSeasonId.value === null) return null;
  return seasonMap.value.get(activeSeasonId.value) || null;
});

// 修改季度切换函数
function handleSeasonChange(value: number | null) {
  if (value === activeSeasonId.value) return;

  // 添加过渡效果
  const container = document.querySelector('.season-info-layout');
  if (container) {
    container.classList.add('transitioning');
    setTimeout(() => {
      activeSeasonId.value = value;
      setTimeout(() => {
        container.classList.remove('transitioning');
      }, 300);
    }, 150);
  }
}

// 监听季度信息变化，自动选择第一个季度
watch(
  () => props.seasons,
  newSeasons => {
    if (newSeasons?.length) {
      activeSeasonId.value = newSeasons[0].season;
    }
  },
  { immediate: true }
);

// 检查内容是否出
function checkContentOverflow(el: HTMLElement) {
  return el.scrollHeight > el.clientHeight;
}


// 处理图片载
async function loadEpisodeImage(episode: EnhancedMediaItem) {
  if (
    (!episode.landscapeAddress && !episode.posterAddress) ||
    imageLoadErrors.value.has(episode.id) ||
    imageLoading.value.has(episode.id) ||
    episodeImages.value[episode.id]
  ) {
    return;
  }

  try {
    imageLoading.value.add(episode.id);
    // 优先使用横向图片
    const imagePath = episode.landscapeAddress || episode.posterAddress;
    if (imagePath) {
      const { data } = await fetchImageData(imagePath);
      if (data) {
        const blob = new Blob([data], { type: 'image/jpeg' });
        const url = URL.createObjectURL(blob);
        episodeImages.value[episode.id] = url;
      }
    }
  } catch (error) {
    console.error(`Failed to load episode image (${episode.id}):`, error);
    imageLoadErrors.value.add(episode.id);
  } finally {
    imageLoading.value.delete(episode.id);
  }
}

// 处理图片加载错误
function handleImageError(id: string) {
  imageLoadErrors.value.add(id);
  if (episodeImages.value[id]) {
    URL.revokeObjectURL(episodeImages.value[id]);
    Reflect.deleteProperty(episodeImages.value, id);
    // delete episodeImages.value[id];
  }
  console.log(`Image load error for episode ${id}`);
}

// 处理图片载成功
function handleImageLoad(id: string) {
  imageLoading.value.delete(id);
  console.log(`Image loaded successfully for episode ${id}`);
}


// 初始化 Intersection Observer
function initIntersectionObserver() {
  if (typeof IntersectionObserver === 'undefined') return;

  observer.value = new IntersectionObserver(
    entries => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const episodeId = entry.target.getAttribute('data-episode-id');
          if (episodeId) {
            const episode = activeSeason.value?.data?.find((ep: EnhancedMediaItem) => ep.id === episodeId);
            // const episode = activeSeason.value?.data?.find(ep => ep.id === episodeId);
            if (episode && (episode.landscapeAddress || episode.posterAddress)) {
              loadEpisodeImage(episode);
            }
            // 取消观察已加载元素
            observer.value?.unobserve(entry.target);
          }
        }
      });
    },
    {
      root: null,
      rootMargin: '50px',
      threshold: 0.1
    }
  );
}

// 修改监听季度变化的逻辑
watch(
  () => activeSeason.value?.data,
  newData => {
    if (newData) {
      // 延迟执行以确保 DOM 已更新
      nextTick(() => {
        // 重初始化 observer
        if (observer.value) {
          observer.value.disconnect();
        }
        initIntersectionObserver();

        // 观察所有剧集片元素
        document.querySelectorAll('.episode-thumb').forEach(el => {
          observer.value?.observe(el);
        });
      });
    }
  },
  { immediate: true }
);

// 组件卸载时清理
onBeforeUnmount(() => {
  // 断开 observer 连接
  if (observer.value) {
    observer.value.disconnect();
    observer.value = null;
  }
  // 清理图片资源
  Object.values(episodeImages.value).forEach(url => {
    URL.revokeObjectURL(url);
  });
  episodeImages.value = {};
  imageLoadErrors.value.clear();
  imageLoading.value.clear();
});

// 格式化时长显示
function formatDuration(minutes: number): string {
  const hours = Math.floor(minutes / 60);
  const remainingMinutes = minutes % 60;

  if (hours > 0) {
    return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
  }
  return `${minutes}m`;
}
</script>

<template>
  <NSpin :show="loading">
    <div class="season-info-container">
      <!-- 顶部季度切换 -->
      <div class="season-switcher">
        <div class="switcher-content">
          <div class="season-tabs">
            <div
              v-for="season in processedSeasons"
              :key="season.season"
              :class="{ active: activeSeasonId === season.season }"
              class="season-tab"
              @click="handleSeasonChange(season.season)"
            >
              {{ $t('page.tv.seasonName', { season: season.season }) }}
              <NTag round size="tiny" type="info">
                {{ season.data?.length || 0 }}
              </NTag>
            </div>
          </div>
        </div>
      </div>

      <!-- 主要内容区域 -->
      <div class="season-info-layout">
        <!-- 左侧季度NFO信息 -->
        <div class="season-nfo-panel">
          <template v-if="activeSeason?.nfo">
            <div class="nfo-header">
              <h2>{{ activeSeason.nfo.title || activeSeason.name }}</h2>
              <div v-if="activeSeason.nfo.originalTitle" class="original-title">
                {{ activeSeason.nfo.originalTitle }}
              </div>
            </div>

            <div class="nfo-meta">
              <NSpace :size="8" wrap>
                <NTag v-if="activeSeason.nfo.year">
                  {{ activeSeason.nfo.year }}
                </NTag>
                <NTag v-if="activeSeason.nfo.rating" :type="getRatingType(activeSeason.nfo.rating)">
                  <template #icon>
                    <div class="i-material-symbols:star" />
                  </template>
                  {{ formatRating(activeSeason.nfo.rating) }}
                </NTag>
              </NSpace>
            </div>

            <div class="nfo-content">
              <!-- 剧情简介 -->
              <div class="nfo-section">
                <div class="section-title">{{ $t('common.overview') }}</div>
                <div class="section-content">
                  {{ activeSeason.nfo.plot || activeSeason.nfo.outline || $t('page.tv.noOverview') }}
                </div>
              </div>

              <!-- 类型标签 -->
              <div v-if="activeSeason.nfo.genres?.length" class="nfo-section">
                <div class="section-title">{{ $t('common.genre') }}</div>
                <div class="section-content">
                  <NSpace :size="4">
                    <NTag v-for="genre in activeSeason.nfo.genres" :key="genre" round size="small">
                      {{ genre }}
                    </NTag>
                  </NSpace>
                </div>
              </div>

              <!-- 演员列表 -->
              <div v-if="activeSeason.nfo.actors?.length" class="nfo-section">
                <div class="section-title">{{ $t('common.actors') }}</div>
                <div class="section-content actors-list">
                  <NTag v-for="actor in activeSeason.nfo.actors" :key="actor.name" round size="small">
                    {{ actor.name }}{{ actor.role ? ` (${actor.role})` : '' }}
                  </NTag>
                </div>
              </div>
            </div>
          </template>
        </div>

        <!-- 右侧剧集列表 -->
        <div class="episode-content">
          <div class="episode-list-header">
            <h3>{{ $t('page.tv.episodeList') }}</h3>
            <div class="episode-list-actions">
              <NSpace :size="8">
                <NButton size="small" text @click="toggleListMode">
                  <template #icon>
                    <div :class="listMode ? 'i-material-symbols:grid-view' : 'i-material-symbols:list'" />
                  </template>
                  {{ listMode ? $t('common.grid') : $t('common.list') }}
                </NButton>
              </NSpace>
            </div>
          </div>

          <div class="episode-list-content">
            <NScrollbar trigger="hover">
              <div :class="{ 'grid-mode': !listMode }" class="episode-items">
                <div
                  v-for="episode in activeSeason?.data"
                  :key="episode.id"
                  :class="{
                    'is-new': episode.isNew
                  }"
                  class="episode-item"
                >
                  <div
                    v-if="episode.landscapeAddress || episode.posterAddress"
                    :data-episode-id="episode.id"
                    class="episode-thumb"
                  >
                    <NSpin
                      :rotate="true"
                      :show="imageLoading.has(episode.id)"
                      :size="32"
                      :stroke-width="4"
                      class="thumb-spinner"
                      stroke="var(--n-primary-color)"
                    >
                      <img
                        v-if="episodeImages[episode.id]"
                        :alt="episode.name"
                        :class="{
                          'image-loaded': !imageLoading.has(episode.id)
                        }"
                        :src="episodeImages[episode.id]"
                        @error="handleImageError(episode.id)"
                        @load="handleImageLoad(episode.id)"
                      />
                    </NSpin>
                    <div class="thumb-overlay" />
                  </div>
                  <div class="episode-header">
                    <div class="episode-number">
                      {{ episode.episodeNumber || 'E??' }}
                    </div>
                    <div class="episode-status">
                      <NTag v-if="episode.isNew" size="tiny" type="success">
                        {{ $t('common.new') }}
                      </NTag>
                    </div>
                  </div>
                  <div class="episode-info">
                    <div class="episode-title">
                      {{ episode.name || $t('common.unnamed') }}
                    </div>
                    <NPopover
                      v-if="episode.nfo?.plot"
                      :delay="100"
                      :style="{
                        padding: '0',
                        border: 'none'
                      }"
                      :duration="100"
                      :keep-alive-on-hover="true"
                      :offset="12"
                      :overlap="true"
                      :raw="true"
                      :show-arrow="false"
                      display-directive="show"
                      :to="false"
                      :width="300"
                      placement="top-start"
                      trigger="hover"
                    >
                      <template #trigger>
                        <div class="episode-plot">
                          {{ episode.nfo.plot }}
                        </div>
                      </template>
                      <div class="plot-popover">
                        {{ episode.nfo.plot }}
                      </div>
                    </NPopover>
                    <div class="episode-meta">
                      <div class="meta-row">
                        <div class="meta-group">
                          <span class="meta-item">
                            <i class="i-material-symbols:schedule" />
                            {{ formatDuration(episode.nfo?.runtime || 0) }}
                          </span>
                          <span class="meta-item">
                            <i class="i-material-symbols:hard-drive" />
                            {{ episode.formattedSize }}
                          </span>
                        </div>
                        <div class="meta-group">
                          <span v-if="episode.resolution" class="meta-item">
                            <i class="i-material-symbols:hd" />
                            {{ episode.resolution }}
                          </span>
                          <span v-if="episode.codec" class="meta-item">
                            <i class="i-material-symbols:code" />
                            {{ episode.codec }}
                          </span>
                          <NPopover
                            :raw="true"
                            :show-arrow="false"
                            :style="{
                              padding: '0',
                              border: 'none',
                              maxWidth: '300px'
                            }"
                            placement="top"
                            trigger="hover"
                          >
                            <template #trigger>
                              <span class="meta-item">
                                <i class="i-material-symbols:subtitles" />
                                {{
                                  episode.subtitle?.length
                                    ? $t('page.tv.episodeDetail.subtitle') + ` (${episode.subtitle.length})`
                                    : $t('page.tv.episodeDetail.noSubtitle')
                                }}
                              </span>
                            </template>
                            <div v-if="episode.subtitle?.length" class="subtitle-list">
                              <div v-for="(sub, index) in episode.subtitle" :key="index" class="subtitle-item">
                                <i class="i-material-symbols:subtitles-outline" />
                                <span class="subtitle-name">{{ sub }}</span>
                              </div>
                            </div>
                          </NPopover>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </NScrollbar>
          </div>
        </div>
      </div>
    </div>
  </NSpin>
</template>

<style scoped>
/* 定义组件级别的CSS变量 */
.season-info-container {
  /* 基础变量 */
  --transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
  --hover-opacity: 0.04;
  --border-opacity: 0.1;
  --card-padding: 12px;
  --border-radius: 8px;
  --animation-duration: 0.3s;
  --font-size-small: 12px;
  --font-size-normal: 14px;
  --font-size-large: 16px;
  --content-height: 80vh;
  --header-height: 64px;

  /* 颜色变量 */
  --n-border-color: rgba(239, 239, 245, 0.12);
  --n-text-color: rgb(51, 54, 57);
  --n-text-color-2: rgb(118, 124, 130);
  --n-text-color-3: rgb(154, 159, 164);
  --n-hover-color: rgba(243, 243, 245, 0.5);
  --n-hover-color-pressed: rgba(243, 243, 245, 0.8);
  --n-primary-color: rgb(64, 158, 255);
  --n-primary-color-hover: rgba(64, 158, 255, 0.1);
  --n-primary-color-rgb: 64, 158, 255;
  --n-success-color: rgb(103, 194, 58);
  --n-scrollbar-color: rgba(0, 0, 0, 0.25);
  --n-scrollbar-color-hover: rgba(0, 0, 0, 0.4);
  --n-box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.12);
  --n-divider-color: rgba(239, 239, 245, 0.2);

  /* 布局变量 */
  --nfo-panel-width: 360px;
  --nfo-panel-width-lg: 320px;
  --nfo-panel-width-md: 280px;
  --episode-grid-min-width: 280px;

  /* 响应式布局调整 */
  @media (max-width: 1400px) {
    --episode-grid-min-width: 240px;
    --nfo-panel-width: var(--nfo-panel-width-lg);
  }

  @media (max-width: 1200px) {
    --episode-grid-min-width: 220px;
    --nfo-panel-width: var(--nfo-panel-width-md);
  }

  @media (max-width: 768px) {
    --episode-grid-min-width: 200px;
    --nfo-panel-width: var(--nfo-panel-width-md);
  }
}

/* 暗色模式变量覆盖 */
:deep(.dark) .season-info-container {
  --n-border-color: rgba(255, 255, 255, 0.12);
  --n-text-color: rgb(255, 255, 255);
  --n-text-color-2: rgba(255, 255, 255, 0.82);
  --n-text-color-3: rgba(255, 255, 255, 0.52);
  --n-hover-color: rgba(255, 255, 255, 0.09);
  --n-hover-color-pressed: rgba(255, 255, 255, 0.13);
  --n-scrollbar-color: rgba(255, 255, 255, 0.2);
  --n-scrollbar-color-hover: rgba(255, 255, 255, 0.3);
  --n-box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.3);
  --n-divider-color: rgba(255, 255, 255, 0.09);
}

/* 顶部季度切换器 */
.season-switcher {
  padding: 16px;
  border-bottom: 1px solid var(--n-border-color);
  position: sticky;
  top: 0;
  z-index: 2;
  min-height: var(--header-height);
  display: flex;
  align-items: center;
  backdrop-filter: blur(8px);

  .switcher-content {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 16px;

    :deep(.n-select) {
      min-width: 200px;
    }
  }
}

/* 主要内容布局 */
.season-info-layout {
  display: flex;
  flex: 1;
  min-height: 0;
  height: calc(var(--content-height) - var(--header-height));
  overflow: hidden;
  position: relative;
}

/* 左侧NFO面板 */
.season-nfo-panel {
  width: var(--nfo-panel-width);
  padding: 16px;
  border-right: 1px solid var(--n-border-color);
  overflow-y: auto;
  position: relative;
  height: 100%;
  flex-shrink: 0;
  min-width: var(--nfo-panel-width);
  max-width: var(--nfo-panel-width);
  transition: all var(--animation-duration) var(--transition-timing);

  &.slide-enter-active,
  &.slide-leave-active {
    transition: transform 0.3s var(--transition-timing);
  }

  &.slide-enter-from {
    transform: translateX(-100%);
  }

  &.slide-leave-to {
    transform: translateX(-100%);
  }

  .nfo-header {
    margin-bottom: 16px;

    h2 {
      font-size: 20px;
      font-weight: 500;
      margin: 0 0 8px;
      line-height: 1.4;
    }

    .original-title {
      font-size: 14px;
      color: var(--n-text-color-3);
      line-height: 1.4;
    }
  }

  .nfo-meta {
    margin-bottom: 24px;
  }

  .nfo-section {
    margin-bottom: 24px;
    position: relative; /* 添加相对定位 */

    &:last-child {
      margin-bottom: 0;
    }

    .section-title {
      font-size: 16px;
      font-weight: 500;
      margin-bottom: 12px;
      color: var(--n-text-color);
    }

    .section-content {
      color: var(--n-text-color-2);
      line-height: 1.6;
      word-break: break-word;
      overflow-wrap: break-word;
      white-space: pre-line;
      max-height: 200px;
      overflow-y: auto;
      position: relative; /* 添加相对定位 */
      padding-bottom: 24px; /* 为渐变遮罩留出空间 */

      /* 添加渐变遮罩 */

      &::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 24px;
        pointer-events: none;
        opacity: 0; /* 默认隐藏 */
        transition: opacity 0.3s var(--transition-timing);
      }

      /* 当内容超出显示渐变遮罩 */

      &.overflow {
        &::after {
          opacity: 1;
        }
      }

      /* 滚动条样式 */

      &::-webkit-scrollbar {
        width: 4px;
      }

      &::-webkit-scrollbar-track {
        background: transparent;
      }

      &::-webkit-scrollbar-thumb {
        background-color: var(--n-scrollbar-color);
        border-radius: 2px;

        &:hover {
          background-color: var(--n-scrollbar-color-hover);
        }
      }
    }
  }

  .actors-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
  }
}

/* 右侧剧集内容 */
.episode-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  position: relative;
  height: 100%;
  overflow: hidden;
  width: calc(100% - var(--nfo-panel-width)); /* 使用剩余宽度 */
  transition: all 0.3s var(--transition-timing);

  &.slide-enter-active,
  &.slide-leave-active {
    transition: all 0.3s var(--transition-timing);
  }

  &.slide-enter-from {
    opacity: 0;
    transform: translateX(20px);
  }

  &.slide-leave-to {
    opacity: 0;
    transform: translateX(20px);
  }

  .episode-list-header {
    padding: 16px;
    border-bottom: 1px solid var(--n-border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: sticky;
    top: 0;
    z-index: 1;
    background: inherit;
    backdrop-filter: blur(8px);

    h3 {
      font-size: 18px;
      font-weight: 500;
      margin: 0;
    }
  }
}

.episode-list-content {
  flex: 1;
  overflow: hidden;

  :deep(.n-scrollbar) {
    height: 100%;
  }

  :deep(.n-scrollbar-container) {
    padding: 16px;
  }
}

.episode-items {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: all var(--animation-duration) var(--transition-timing);

  &.grid-mode {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 16px;
    align-items: stretch;
  }
}

.episode-item {
  padding: var(--card-padding);
  border: 1px solid var(--n-border-color);
  border-radius: var(--border-radius);
  transition: transform 0.2s var(--transition-timing),
  box-shadow 0.2s var(--transition-timing),
  background-color 0.2s var(--transition-timing);
  cursor: pointer;
  background: var(--n-hover-color);
  display: flex;
  flex-direction: column;
  height: 100%;
  transform-origin: center;
  will-change: transform;
  backface-visibility: hidden;
  perspective: 1000px;
  transform: translateZ(0);

  /* 列表模式 */

  .episode-items:not(.grid-mode) & {
    flex-direction: row;
    height: auto;
    gap: 16px;
    align-items: flex-start;

    .episode-thumb {
      width: 240px;
      height: 135px;
      margin-bottom: 0;
      flex-shrink: 0;
    }

    .episode-info {
      flex: 1;
      min-width: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      height: 135px;
    }
  }

  &:focus-within {
    outline: 2px solid var(--n-primary-color);
    outline-offset: -2px;
  }

  &:hover {
    transform: translateY(-2px) translateZ(0);
    box-shadow: var(--n-box-shadow);
    background: var(--n-hover-color-pressed);
    z-index: 1;

    .episode-thumb img {
      transform: scale(1.05) translateZ(0);
    }

    .episode-meta .meta-group {
      opacity: 1;
    }

    .episode-plot {
      opacity: 1;
    }
  }

  .episode-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
    flex-shrink: 0;
  }

  .episode-info {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    padding: 8px 0;
  }

  .episode-title {
    font-weight: 500;
    margin-bottom: 4px;
    color: var(--n-text-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--font-size-normal);
  }

  .episode-plot {
    font-size: 12px;
    color: var(--n-text-color-3);
    margin-bottom: 4px;
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    flex: 1;
    min-height: 36px;
    opacity: 0.8;
    position: relative;
    cursor: help;
    transition: opacity 0.3s var(--transition-timing);

    &:hover {
      opacity: 1;
    }
  }

  .episode-meta {
    margin-top: auto;
    font-size: 12px;
    color: var(--n-text-color-3);
    flex-shrink: 0;
    padding-top: 4px;
    border-top: 1px solid var(--n-border-color);

    .meta-row {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      align-items: center;
      justify-content: space-between;

      &:not(:last-child) {
        margin-bottom: 8px;
      }

      .meta-group {
        display: flex;
        gap: 12px;
        align-items: center;
        opacity: 0.8;
        transition: opacity 0.3s var(--transition-timing);
      }
    }
  }

  &.is-new {
    border-color: var(--n-success-color);

    .episode-title {
      color: var(--n-success-color);
    }
  }
}

/* 暗色模式适配 */
:deep(.dark) {
  .season-nfo-panel,
  .episode-content {
    background: rgba(24, 24, 28, 0.95);
  }

  .season-switcher {
    background: rgba(24, 24, 28, 0.98);
  }

  .season-nfo-panel:after {
    background: linear-gradient(
      to bottom,
      transparent,
      rgba(255, 255, 255, 0.1) 10%,
      rgba(255, 255, 255, 0.1) 90%,
      transparent
    );
  }

  .episode-item {
    background: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(8px);

    &:hover {
      background: rgba(255, 255, 255, 0.06);
      border-color: rgba(255, 255, 255, 0.2);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
    }

    &.is-new {
      border-color: var(--n-success-color);

      .episode-title {
        color: var(--n-success-color);
      }
    }
  }

  .nfo-section {
    .section-content {
      &::after {
        background: linear-gradient(to bottom, transparent, rgba(24, 24, 28, 0.95) 90%);
      }

      &::-webkit-scrollbar-thumb {
        background-color: rgba(255, 255, 255, 0.2);

        &:hover {
          background-color: rgba(255, 255, 255, 0.3);
        }
      }
    }
  }

  .episode-plot {
    &:hover {
      background: rgba(24, 24, 28, 0.95);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
      backdrop-filter: blur(8px);
    }
  }
}

/* 添加滚动条样式 */
.season-nfo-panel,
.episode-list-content {
  :deep(.n-scrollbar) {
    .n-scrollbar-rail {
      opacity: 0;
      transition: opacity 0.2s var(--transition-timing);
    }

    &:hover .n-scrollbar-rail {
      opacity: 1;
    }
  }
}

.season-tabs {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;

  &::-webkit-scrollbar {
    height: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background-color: var(--n-scrollbar-color);
    border-radius: 2px;
  }
}

.season-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 16px;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.3s var(--transition-timing);
  border: 1px solid transparent;

  &:hover {
    background: var(--n-hover-color);
  }

  &.active {
    background: var(--n-primary-color-hover);
    color: var(--n-primary-color);
    border-color: var(--n-primary-color);
  }
}

.episode-items {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;

  &.grid-mode {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 16px;
    align-items: stretch;
  }
}

.episode-item {
  margin-bottom: 0;
}

/* 暗色模式适配 */
:deep(.dark) {
  .season-tab {
    &:hover {
      background: rgba(255, 255, 255, 0.06);
    }

    &.active {
      background: rgba(var(--n-primary-color-rgb), 0.15);
    }
  }
}

/* 添加过渡效果 */
.transitioning {
  .season-nfo-panel,
  .episode-content {
    transition: all var(--animation-duration) var(--transition-timing);
  }
}

/* 修改演员列表样式 */
.actors-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* 图片相关样式统一管理 */
.episode-thumb {
  position: relative;
  width: 100%;
  height: 180px;
  margin-bottom: 8px;
  border-radius: var(--border-radius);
  overflow: hidden;

  &::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(to bottom, transparent 50%, rgba(0, 0, 0, 0.6));
    opacity: 0;
    transition: opacity 0.3s var(--transition-timing);
    pointer-events: none;
  }

  .thumb-spinner {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }

  :deep(.n-spin-container) {
    width: 100%;
    height: 100%;
  }

  img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: transparent;
    display: block;
    opacity: 0;
    transition: transform 0.15s var(--transition-timing),
    opacity 0.15s var(--transition-timing);
    will-change: transform, opacity;
    backface-visibility: hidden;
    transform: translateZ(0);

    &.image-loaded {
      opacity: 1;
    }
  }
}

.episode-item:hover {
  .episode-thumb {
    &::after {
      opacity: 1;
    }

    img {
      transform: scale(1.05) translateZ(0);
    }
  }
}

/* 响应式调整 */
@media (max-width: 1400px) {
  .episode-content {
    width: calc(100% - var(--nfo-panel-width-lg));
  }

  .episode-items.grid-mode {
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  }
}

@media (max-width: 1200px) {
  .episode-content {
    width: calc(100% - var(--nfo-panel-width-md));
  }

  .episode-items.grid-mode {
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  }
}

@media (max-width: 768px) {
  .episode-items.grid-mode {
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  }
}

/* 弹出层样式 */
.plot-popover {
  max-width: 300px;
  max-height: 200px;
  overflow-y: auto;
  font-size: var(--font-size-small);
  line-height: 1.6;
  padding: 8px 12px;
  border-radius: var(--border-radius);
  box-shadow: var(--n-box-shadow);
  animation: fadeIn 0.2s var(--transition-timing);
  word-break: break-word;
  white-space: pre-line;
  color: var(--n-text-color);
  position: relative;
  z-index: 1000;
  transform-origin: top;
  border: 1px solid var(--n-border-color);
  backdrop-filter: blur(12px);
  min-width: 200px;

  &::-webkit-scrollbar {
    width: 4px;
  }

  &::-webkit-scrollbar-track {
    background: transparent;
  }

  &::-webkit-scrollbar-thumb {
    background-color: var(--n-scrollbar-color);
    border-radius: 2px;

    &:hover {
      background-color: var(--n-scrollbar-color-hover);
    }
  }
}

/* 动画定义 */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 暗色模式适配 */
:deep(.dark) {
  .plot-popover {
    background: rgba(24, 24, 28, 0.98);
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(12px);
    color: var(--n-text-color);
    border: 1px solid rgba(255, 255, 255, 0.15);

    &::before {
      content: '';
      position: absolute;
      inset: 0;
      background: rgba(0, 0, 0, 0.2);
      z-index: -1;
      border-radius: inherit;
    }
  }
}

.subtitle-info {
  cursor: pointer;
  margin-left: 4px;
  color: var(--n-text-color-3);
  transition: color 0.2s var(--transition-timing);

  &:hover {
    color: var(--n-text-color);
  }
}

.subtitle-list {
  max-height: 200px;
  overflow-y: auto;
  font-size: var(--font-size-small);
  padding: 8px;
  border-radius: var(--border-radius);

  .subtitle-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px;
    transition: background-color 0.2s var(--transition-timing);

    &:hover {
      background-color: var(--n-hover-color);
    }

    &:not(:last-child) {
      border-bottom: 1px solid var(--n-divider-color);
    }

    .subtitle-name {
      flex: 1;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      color: var(--n-text-color);
    }

    i {
      color: var(--n-text-color-3);
      font-size: 16px;
    }
  }

  &::-webkit-scrollbar {
    width: 4px;
  }

  &::-webkit-scrollbar-track {
    background: transparent;
  }

  &::-webkit-scrollbar-thumb {
    background-color: var(--n-scrollbar-color);
    border-radius: 2px;

    &:hover {
      background-color: var(--n-scrollbar-color-hover);
    }
  }
}
</style>
